# Declarative 'react-babylonjs'

This page demonstrates how to create a truly reactive Babylon.js app. We'll
learn how to make custom Babylon React components, and how to use some helpful
hooks like `useScene`, `useBeforeRender`.

## Creating a Basic Scene

Let's take a look at a basic `react-babylonjs` scene using the `Engine` and
`Scene` components of `react-bablylonjs`. These will connect and create an HTML
canvas, Engine and Scene with a render loop. Everything you might like to add to
a scene can be added declaratively in the `Scene`. Note we can also pass in
props like below with `antialias`/`antialias={true}` to the Babylon.js Engine.

```tsx
import { Engine, Scene } from 'react-babylonjs'

const BabylonApp: FC = ({ children }) => (
  <div style={{ flex: 1, display: 'flex' }}>
    <Engine antialias adaptToDeviceRatio canvasId="babylon-canvas">
      <Scene>{children}</Scene>
    </Engine>
  </div>
)
```

If you wanted to re-use some components you could flow down your scene graph as
shown below. The React concept _composition_ will be demonstrated further in
these guides in a Babylon context.

```tsx
import { FC } from 'react'
import { Engine, Scene } from 'react-babylonjs'

const BasicScene: FC = ({ children }) => (
  <Engine antialias adaptToDeviceRatio canvasId="babylon-canvas">
    <Scene>{children}</Scene>
  </Engine>
)

const BabylonApp: FC = ({ children }) => (
  <div style={{ flex: 1, display: 'flex' }}>
    <BasicScene>{children}</BasicScene>
  </div>
)
```

## Adding light, camera, and surface

The scene above is empty and won't display anything. To see something, we need
to add light, a camera, and something to look at. Let's do that now.

As we go along, it's important to understand a concept known as
[intrinsic JSX](https://www.typescriptlang.org/docs/handbook/jsx.html#intrinsic-elements).
Renderers treat them as `Host Elements` as opposed to React Components, much
like the `react-dom` renderer would for HTML elements like `div` or `span`. We
had to explicitly import `Engine` and `Scene`, but there are many Babylon.js
elements that will be understood by React thanks to this library. We will use
`<freeCamera ... />`, `<hemisphericLight ... />`, and `<ground ... />`. Those
are all _intrinsic_, meaning we don't need an `import` statement to use them.
They are understood by your IDE and include intellisense and compile time
warnings. In a Babylon.js application it means you can add your cameras, lights,
etc. in that familiar declarative way to your scene:

```tsx
<Scene>
  <freeCamera name="camera1" position={new Vector3(0, 5, -10)} setTarget={[Vector3.Zero()]} />

  <hemisphericLight name="light1" intensity={0.7} direction={new Vector3(0, 1, 0)} />

  <ground name="ground" width={6} height={6} />
</Scene>
```

Click the **"code"** tab to see the code and you can toggle between TypeScript
or JavaScript.

<code src="./react-with-declarative-babylonjs/BasicScene.tsx" />

## Adding an object to the scene

Before we move on, let's add a standard box to the scene and see how the props
work.

If we create a box in Babylon.js imperatively you could call
[CreateBox](https://doc.babylonjs.com/typedoc/modules/BABYLON#CreateBox-2):

```tsx
// doesn't need to be MeshBuilder - there are creation methods that can be imported directly.
import { MeshBuilder } from '@babylonjs/core'

// NOTE: you need to pass in `scene` object yourself.
const box = MeshBuilder.CreateBox('box', { size: 2 }, scene)
box.position = new Vector3(0, 1, 0)
box.rotation = Vector3.Zero()
```

The equivalent way using `react-babylonjs`:

```tsx
<box name="box" size={2} position={new Vector3(0, 1, 0)} rotation={Vector3.Zero()} />
```

You may be wondering why the element is called "box" - that's because we are
using the factory creation method name (without "Create" prefix).

What's important to note is that the constructor arguments `name` and `size` are
passed in and are used once only. The resulting object that you have props
available for is a Mesh object, which has properties like `position` and
`rotation`. When non-constructor props get new values they are set on the
underlying Babylon.js object automatically - the same as you may be accustomed
to with CSS or element attributes in DOM. Lastly, notice that we didn't need to
pass in a scene object - that is done automatically.

<code src="./react-with-declarative-babylonjs/LoneBox.tsx" />

Let's quickly look with FreeCamera at a regular Babylon.js object that's not
using a creation method to see how most objects are created.

This is how we'd create a FreeCamera declaratively:

```tsx
import { FreeCamera, Vector3 } from '@babylonjs/core'
var camera = new FreeCamera('camera1', new Vector3(0, 5, -10), scene)

// This targets the camera to scene origin
camera.setTarget(Vector3.Zero())
```

This is the equivalent in `react-babylonjs`:

```tsx
<freeCamera name="camera1" position={new Vector3(0, 5, -10)} setTarget={[Vector3.Zero()]} />
```

In this case we passed in the `name` "camera1" and initial `position`. When
calling a method we can use an array for the parameters. The `position` is also
a property, so we can update that prop to change it as well.
